using System;
using System.Security.Cryptography;
using System.Text;

namespace Hash
{
  /// <summary>Class used to generate and check hashes.</summary>
  public class Hash
  {
    /// <summary></summary>
    public Hash() { }

    #region Hash Choices
    /// <summary>The wanted hash function.</summary>
    public enum HashType : int
    {
      /// <summary>MD5 Hashing</summary>
      MD5,
      /// <summary>SHA1 Hashing</summary>
      SHA1,
      /// <summary>SHA256 Hashing</summary>
      SHA256,
      /// <summary>SHA384 Hashing</summary>
      SHA384,
      /// <summary>SHA512 Hashing</summary>
      SHA512
    } /* HashType */
    #endregion

    #region Public Methods
    /// <summary>Generates the hash of a text.</summary>
    /// <param name="strPlain">The text of which to generate a hash of.</param>
    /// <param name="hshType">The hash function to use.</param>
    /// <returns>The hash as a hexadecimal string.</returns>
    public static string GetHash(string strPlain, HashType hshType)
    {
      string strRet;
      switch (hshType)
      {
        case HashType.MD5: strRet = GetMD5(strPlain); break;
        case HashType.SHA1: strRet = GetSHA1(strPlain); break;
        case HashType.SHA256: strRet = GetSHA256(strPlain); break;
        case HashType.SHA384: strRet = GetSHA384(strPlain); break;
        case HashType.SHA512: strRet = GetSHA512(strPlain); break;
        default: strRet = "Invalid HashType"; break;
      }
      return strRet;
    } /* GetHash */

    /// <summary>Checks a text with a hash.</summary>
    /// <param name="strOriginal">The text to compare the hash against.</param>
    /// <param name="strHash">The hash to compare against.</param>
    /// <param name="hshType">The type of hash.</param>
    /// <returns>True if the hash validates, false otherwise.</returns>
    public static bool CheckHash(string strOriginal, string strHash, HashType hshType)
    {
      string strOrigHash = GetHash(strOriginal, hshType);
      return (strOrigHash == strHash);
    } /* CheckHash */
    #endregion

    #region Hashers
    private static string GetMD5(string strPlain)
    {
      UnicodeEncoding UE = new UnicodeEncoding();
      byte[] HashValue, MessageBytes = UE.GetBytes(strPlain);
      MD5 md5 = new MD5CryptoServiceProvider();
      string strHex = "";

      HashValue = md5.ComputeHash(MessageBytes);
      foreach (byte b in HashValue)
      {
        strHex += String.Format("{0:x2}", b);
      }
      return strHex;
    } /* GetMD5 */

    private static string GetSHA1(string strPlain)
    {
      UnicodeEncoding UE = new UnicodeEncoding();
      byte[] HashValue, MessageBytes = UE.GetBytes(strPlain);
      SHA1Managed SHhash = new SHA1Managed();
      string strHex = "";

      HashValue = SHhash.ComputeHash(MessageBytes);
      foreach (byte b in HashValue)
      {
        strHex += String.Format("{0:x2}", b);
      }
      return strHex;
    } /* GetSHA1 */

    private static string GetSHA256(string strPlain)
    {
      UnicodeEncoding UE = new UnicodeEncoding();
      byte[] HashValue, MessageBytes = UE.GetBytes(strPlain);
      SHA256Managed SHhash = new SHA256Managed();
      string strHex = "";

      HashValue = SHhash.ComputeHash(MessageBytes);
      foreach (byte b in HashValue)
      {
        strHex += String.Format("{0:x2}", b);
      }
      return strHex;
    } /* GetSHA256 */

    private static string GetSHA384(string strPlain)
    {
      UnicodeEncoding UE = new UnicodeEncoding();
      byte[] HashValue, MessageBytes = UE.GetBytes(strPlain);
      SHA384Managed SHhash = new SHA384Managed();
      string strHex = "";

      HashValue = SHhash.ComputeHash(MessageBytes);
      foreach (byte b in HashValue)
      {
        strHex += String.Format("{0:x2}", b);
      }
      return strHex;
    } /* GetSHA384 */

    private static string GetSHA512(string strPlain)
    {
      UnicodeEncoding UE = new UnicodeEncoding();
      byte[] HashValue, MessageBytes = UE.GetBytes(strPlain);
      SHA512Managed SHhash = new SHA512Managed();
      string strHex = "";

      HashValue = SHhash.ComputeHash(MessageBytes);
      foreach (byte b in HashValue)
      {
        strHex += String.Format("{0:x2}", b);
      }
      return strHex;
    } /* GetSHA512 */
    #endregion
  } /* Hash */
} /* Hash */